package ua.com.softway.db;

import java.util.List;

import javax.persistence.NoResultException;

import org.hibernate.ejb.HibernateQuery;

public class Query<T> {

    private static EntityPermissions permissions = new EntityPermissions() { 
        public boolean hasPermissions(Object entity) {
            return true;
        }
    };
    
    private static int configMaxResults = Integer.MAX_VALUE;
    
    public static void configure(int maxResults, EntityPermissions permissions) {
        configMaxResults = maxResults;
        Query.permissions = permissions;
    }
    
    
    public static <T> T find(Class<T> entityClass, Object entityId) {
        try {
            T entity = Persistence.current().find(entityClass, entityId);
            
            if (!permissions.hasPermissions(entity)) return null;
            
            return entity;
        } catch (NoResultException e) {
            return null;
        }
    }

    protected javax.persistence.Query query;
    private Integer maxResults;

    public Query(Class<T> clazz, String where) {
        this("from " + clazz.getSimpleName() + " where " + where);
    }

    public Query(Class<T> clazz, String where, String order) {
        this("from " + clazz.getSimpleName() + " where " + where + " order by " + order + " asc");
    }

    public Query(String hql) {
        query = Persistence.current().createQuery(hql);
        maxResults = configMaxResults;
    }

    public Query(javax.persistence.Query query) {
        this.query = query;
        this.maxResults = configMaxResults;
    }

    public void setFirstResult(int i) {
        query.setFirstResult(i);
    }

    public void setMaxResults(int i) {
        if (i < maxResults) maxResults = i;
    }

    @SuppressWarnings("unchecked")
    public List<T> getResultList() {
        if (maxResults > 0)
            query.setMaxResults(maxResults);
        
        return query.getResultList();
    }

    @SuppressWarnings("unchecked")
    public T getSingleResult() {
        query.setFirstResult(0);
        query.setMaxResults(1);

        try {
            return (T) query.getSingleResult();
        } catch(NoResultException e) {
            return null;
        }
    }

    public Query<T> setParameter(String name, Object object) {
        query.setParameter(name, object);
        
        return this;
    }

    public Query<T> setParameter(int i, Object object) {
        query.setParameter(i, object);

        return this;
    }
    
    public void setCacheable(boolean b) {
        query.setHint("org.hibernate.cacheable", b);
    }
    
    public javax.persistence.Query impl() {
        return query;
    }
    
    public void setFetchSize(int fetchSize) {
        ((HibernateQuery) impl()).getHibernateQuery().setFetchSize(fetchSize);
    }
}
